#include "lib/lock.h"
#include "lib/print.h"
#include "dev/timer.h"
#include "memlayout.h"
#include "riscv.h"

/*-------------------- 工作在M-mode --------------------*/

// in trap.S M-mode时钟中断处理流程()
extern void timer_vector();

// 每个CPU在时钟中断中需要的临时空间(考虑为什么可以这么写)
static uint64 mscratch[NCPU][5];

// 时钟初始化
// called in start.c
void timer_init()
{
    int id = r_mhartid();
    
    // 设置当前 CPU 的 CLINT_MTIMECMP 以便触发第一次中断
    *(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + INTERVAL;

    uint64 *scratch = &mscratch[id][0];
    scratch[3] = (uint64)CLINT_MTIMECMP(id);  // 存储MTIMECMP地址
    scratch[4] = INTERVAL;                    // 存储中断间隔值
    w_mscratch((uint64)scratch);              // 将scratch地址写入mscratch寄存器


    // 设置M-mode trap handler的入口地址，即中断处理程序
    w_mtvec((uint64)timer_vector);

    // 启用M-mode中断
    w_mstatus(r_mstatus() | MSTATUS_MIE);

    // 启用M-mode时钟中断
    w_mie(r_mie() | MIE_MTIE);
}


/*--------------------- 工作在S-mode --------------------*/

// 系统时钟
timer_t sys_timer;

// 时钟创建(初始化系统时钟)
void timer_create()
{
    sys_timer.ticks = 0; // 初始化 ticks
    spinlock_init(&sys_timer.lk,"tm"); // 初始化自旋锁
}

// 时钟更新(ticks++ with lock)
void timer_update()
{
    spinlock_acquire(&sys_timer.lk); // 获取锁
    sys_timer.ticks++; // 更新 ticks
    spinlock_release(&sys_timer.lk); // 释放锁
}

// 返回系统时钟ticks
uint64 timer_get_ticks()
{
    uint64 current_ticks;

    spinlock_acquire(&sys_timer.lk); // 获取锁
    current_ticks = sys_timer.ticks; // 获取 ticks
    spinlock_release(&sys_timer.lk); // 释放锁

    return current_ticks;
}